<?php
namespace app\common\event;
use app\api\facade\Jwt;
use app\common\model\CrmCustomerLogs;
use app\common\model\CrmCustomers;
use app\common\model\CrmFieldConfigs;
use app\common\model\SystemRegion;
use app\common\model\SystemUser;
use app\common\service\SystemDictService;
use support\Log;
use Tinywan\Jwt\JwtToken;


class CustomerChanged
{
    public function handle($e): void
    {
        try {
            $res = $this->resolveIdentity();
            $role = $res['source'] ?? 'system';
            $operatorId = $res['user_id'] ?? 0;
            if (!empty($e['description'])) {
                $desc = is_array($e['description']) ? $e['description'] : [$e['description']];
            } else {
                $desc = $this->generateDescription(
                    $e['originalCustomerData'] ?? [],
                    $e['newCustomerData'] ?? [],
                    $e['originalMetasData'] ?? [],
                    $e['newMetasData'] ?? []
                );
            }
            if (!empty($e['_description'])) {
                $desc[] = $e['_description'];
            }
            
            CrmCustomerLogs::insert([
                'customer_id'   => $e['customerId'] ?? 0,
                'event_type'    => $e['eventType'] ?? '',
                'operator_id'   => $operatorId,
                'operator_role' => $role,
                'description'   => json_encode($desc, JSON_UNESCAPED_UNICODE),
                //'diff'          => json_encode($desc, JSON_UNESCAPED_UNICODE),
                'ip'            => request()->getRemoteIp(),
                'ua'            => request()->header('User-Agent'),
            ]);
        } catch (\Throwable $e) {
            Log::error('客户变更日志记录失败: ' . $e->getMessage());
        }
    }

    private function resolveIdentity(): array
    {
        try {
            $auth = request()->header('Authorization');
            if (!$auth || !str_starts_with($auth, 'Bearer ')) {
                return ['system', 0];
            }
            $token = substr($auth, 7);
  
            // 根据路由前缀区分前后端
            $isAdmin = str_starts_with(request()->path(), '/admin/');
            $isApi = str_starts_with(request()->path(), '/api/');
            $data = [
                'source' => '',
                'user_id' => 0,
            ];

            if ($isAdmin) {
                $token = JwtToken::getExtend();
                $data = [
                    'source' => 'admin',
                    'user_id' => $token['id'] ?? 0,
                ];
            } elseif ($isApi) {
                $token = Jwt::verifyToken($token);
                $data = [
                    'source' => 'api',
                    'user_id' => $token['user_id'] ?? 0,
                ];
            }
            return $data;
        } catch (\Throwable $e) {
            Log::error('客户变更日志记录失败: ' . $e->getMessage());
            return ['system', 0];
        } 
    }
    
    private function generateDescription(array $oldC, array $newC, array $oldM, array $newM): array
    {
        $lines = [];
        unset($newC['follow_up_count']);
        // 1. 主表字段
        foreach ($newC as $k => $v) {
            $label = CrmCustomers::$fieldLabels[$k] ?? $k;
            $old   = $oldC[$k] ?? '';
            $new   = $v ?? '';
            if ($old == $new) continue;
            if (in_array($k, ['create_time', 'update_time', 'delete_time', 'created_by', 'updated_by'])) {
                continue;
            }
            
            $oldLabel = $this->resolveValue($k, $old);
            $newLabel = $this->resolveValue($k, $new);
            if ($newLabel === '') {
                $lines[] = "将 {$label} 置空";
            } elseif ($oldLabel === '') {
                $lines[] = "将 {$label} 设置为 {$newLabel}";
            } else {
                $lines[] = "将 {$label} 从 {$oldLabel} 更新为 {$newLabel}";
            }
        }
        
        // 2. 动态字段
        $configs = CrmFieldConfigs::select()->toArray();
        $configs = array_column($configs, null, 'name');

        foreach ($newM as $k => $v) {
            if (!isset($configs[$k])) continue;
            $label = $configs[$k]['label'] ?? $k;
            $old   = $oldM[$k] ?? '';
            $new   = $v ?? '';
            if ($old == $new) continue;
            $oldLabel = $this->resolveMetaValue($k, $old, $configs);
            $newLabel = $this->resolveMetaValue($k, $new, $configs);
            if ($newLabel === '') {
                $lines[] = "将 {$label} 置空";
            } elseif ($oldLabel === '') {
                $lines[] = "将 {$label} 设置为 {$newLabel}";
            } else {
                $lines[] = "将 {$label} 从 {$oldLabel} 更新为 {$newLabel}";
            }
        }
        
        return $lines;
    }
    
    private function resolveValue(string $key, string $value, array $configs = []): string
    {
        return match ($key) {
            'province_id',
            'city_id',
            'area_id' => SystemRegion::where('id', $value)->value('name') ?? $value,
            'stage' => array_column(SystemDictService::getDictData('customer_stage'), 'label', 'value')[$value] ?? $value,
            'user_id' => SystemUser::where('id', $value)->value('nickname') ?? $value,
            'status' => array_column(SystemDictService::getDictData('data_status'), 'label', 'value')[$value] ?? $value,
            default => $value
        };
    }
    
    private function resolveMetaValue(string $key, string $value, array $configs): string
    {
        // 字段配置不存在或无 options 直接返回原值
        if (!isset($configs[$key]) || empty($configs[$key]['options'])) {
            return $value;
        }
        
        $options = json_decode($configs[$key]['options'], true) ?? [];
        if (!is_array($options)) {
            return $value;
        }
        $options = array_column($options, 'label', 'value');
        // 多选值（逗号分割）
        if ($configs[$key]['type'] === 'checkbox' && str_contains($value, ',')) {
            $values = explode(',', $value);
            return implode('、', array_map(fn($v) => $options[$v] ?? $v, $values));
        }
        // 单选 / 下拉
        return $options[$value] ?? $value;
    }
    
    
}